﻿using System;
using System.Collections;
using TMPro;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.TextCore.Text;


namespace Gameplay
{
    public enum CharacterState 
    {
        Idle,
        Move,
        Jump,
        Attack,
        Die,
        Damage,
        Block,
    }

    public class Character : MonoBehaviour
    {
        private Animator _animator;
        private InfomediaryAnimation _infomediaryAnimation;
        private Rigidbody _rb;
        private Sensor _sensor;
        private CapsuleCollider _collider;
        private SkillManager _skillManager;
        private ParticleManager _particleManager;

        public Animator Anim => _animator;
        public SkillManager SkillManager => _skillManager;
        public Rigidbody RB => _rb;
        public ParticleManager ParticleManager => _particleManager;


        [SerializeField]private Weapon _weapon;
        [SerializeField] private float _moveSpeed;
        [SerializeField] private float _rotateSpeed;
        [SerializeField] private float _force;
        [SerializeField] private float _maxHP;

        public Weapon Weapon => _weapon;


        public CharacterState State;

        private Vector3 _direction;
        public Vector3 Direction => _direction; 
     
        private float _currentHP;

        private bool _die=false;


        private bool _damage = false;

        public bool IsBlock;

        public bool Dead => _die;
        public bool Attacking { get; set; }
        public bool Damage => _damage;

        public float HP 
        {
            get
            {
                return _currentHP;
            }
            set
            {
                if (value <= 0) 
                {
                    _currentHP = 0;
                   
                    Die();
                    
                }
                else if (value > _maxHP) 
                {
                    _currentHP = _maxHP;
                }
                else 
                {
                    _currentHP = value;
                }
                
            }
        }
        
        private void Awake()
        {
            _animator = GetComponent<Animator>();
            if (_animator == null)
            {
                _animator = GetComponentInChildren<Animator>();
            }
            _rb = GetComponent<Rigidbody>();
            _sensor = GetComponentInChildren<Sensor>();
            _collider = GetComponent<CapsuleCollider>();
            _skillManager=GetComponent<SkillManager>();
            _infomediaryAnimation = GetComponentInChildren<InfomediaryAnimation>();
            _particleManager = GetComponentInChildren<ParticleManager>();
        }

        private void Start()
        {
            State = CharacterState.Idle;
            if (_weapon != null) 
            {
                _weapon.SetOwner(this);
            }
            
            HP = _maxHP;
            _collider.enabled = true;
            _skillManager.Init(this);
            _infomediaryAnimation.OnSkillStartEvent += SkillStart;
            _infomediaryAnimation.OnSkillTriggerEvent += SkillTrigger;
            _infomediaryAnimation.OnSkillFinishEvent += SkillFinish;
            _infomediaryAnimation.OnSkillEndEvent += SkillEnd;
        }
        private void OnDisable()
        {
            _infomediaryAnimation.OnSkillStartEvent -= SkillStart;
            _infomediaryAnimation.OnSkillTriggerEvent -= SkillTrigger;
            _infomediaryAnimation.OnSkillFinishEvent -= SkillFinish;
            _infomediaryAnimation.OnSkillEndEvent -= SkillEnd;
        }

        private void SkillTrigger()
        {
            _skillManager.SkillTrigger();
        }

        private void SkillStart()
        {
            _skillManager.OnSkill();
        }
        private void SkillFinish()
        {
            _skillManager.SkillFinish();
        }
        private void SkillEnd()
        {
            _skillManager.SkillEnd();
        }
        

        private void Update()
        {
            if (State == CharacterState.Damage) 
            {
                return;
            }
            _animator.SetFloat("yVelocity", _rb.velocity.y);
            _animator.SetBool("isGrounded", _sensor.IsGrounded);
            _animator.SetFloat("Velocity", _direction.magnitude * _moveSpeed, 0.1f, Time.deltaTime);

            if (_sensor.IsGrounded)
            {
                _animator.SetBool("Jumping", false);
                
            }
            _skillManager.SkillUpdate();
        }

        public void Idle()
        {
            State = CharacterState.Idle;
            _animator.SetBool("Moving", false);
            _direction = Vector3.zero;
            _rb.velocity = new Vector3(0, _rb.velocity.y, 0);
        }
        public void Move(Vector3 direction,float speed)
        {
            Rotate(direction);
            Vector3 targetPosition = _rb.position + speed * direction.normalized * Time.deltaTime;
            Vector3 targetVelocity = (targetPosition - transform.position) / Time.deltaTime;
            
            _rb.velocity = new Vector3(targetVelocity.x, _rb.velocity.y, targetVelocity.z);
            Debug.Log(_rb.velocity);

            _animator.SetFloat("Velocity", direction.magnitude* _moveSpeed, 0.3f, Time.deltaTime);
        }

        public void MoveTo(Vector3 direction)
        {

            if (CanMove())
            {

                State = CharacterState.Move;
                _animator.SetBool("Moving", true);

                _direction = direction;
               
                Move(_direction,_moveSpeed);
            }
        }

        public bool MoveToTarget(Vector3 targetPos)
        {
            if (CanMove()) 
            {
                State = CharacterState.Move;
                _animator.SetBool("Moving", true);

                Vector3 direction;
                targetPos.y = 0;
                Vector3 currentPos = new Vector3(transform.position.x, 0, transform.position.z);
                if ((targetPos - currentPos).magnitude <= 0.3f)
                {
                    direction = Vector3.zero;
                    _rb.velocity = new Vector3(0, _rb.velocity.y, 0);
                    return true;
                }
                else
                {
                    direction = targetPos - currentPos;
                    direction.Normalize();
                    Move(direction,_moveSpeed);
                    return false;
                }
            }
            return false;

        }

        /// <summary>
        /// 角色转向
        /// </summary>
        private void Rotate(Vector3 direction)
        {
            direction.y = 0;
            Vector3 targetForward = Vector3.RotateTowards(transform.forward, direction.normalized, _rotateSpeed * Time.deltaTime, .01f);
            Quaternion rotate = Quaternion.LookRotation(targetForward);
            transform.rotation = rotate;
        }

        public void Jump()
        {
            if (CanJump())
            {
                if (State != CharacterState.Jump)
                {
                    State = CharacterState.Jump;

                    var dir=new Vector3(0, 1, _direction.normalized.z);
                    dir.Normalize();
                    _rb.AddForce(dir * _force, ForceMode.Impulse);
                    StartCoroutine(WaitForJump());
                }
            }
        }

        private IEnumerator WaitForJump()
        {
            yield return null;  
            _animator.SetBool("Jumping", true);
        }


        public void TakeDamage(Character target,float damageValue, Vector3 closesPoint)
        {

            if (!_damage)
            {
                _rb.velocity = new Vector3(0,_rb.velocity.y,0);
                _damage = true;
                State = CharacterState.Damage;
                
       
                transform.LookAt(target.transform.position);
                if (target.SkillManager.CurrentUseSkill.Config.HitSound != null)
                {
                    AudioManager.Instance.PlaySound(target.SkillManager.CurrentUseSkill.Config.HitSound);
                }
                if (target.SkillManager.CurrentUseSkill.Config.HitVFX != null)
                {

                    _particleManager.PlayEffect(target.SkillManager.CurrentUseSkill.Config.HitVFX, closesPoint);
                }
                if (!IsBlock) 
                {
                    _animator.SetTrigger("DamageLight");
                    HP -= damageValue;
                }
                else 
                {
                   
                    _animator.SetTrigger("BlockHit");
                }
                
                StartCoroutine(WaitForRecover());
            }
        }

        private IEnumerator WaitForRecover()
        {
            yield return new WaitForSeconds(1f);
            _damage = false;
            State = CharacterState.Idle;
        }

        public void Die()
        {
            if(State== CharacterState.Die) 
            {
                return;
            }
            if (!_die) 
            {
                _collider.enabled = false;

                _die = true;
                _rb.velocity = new Vector3(0, _rb.velocity.y, 0);
                _rb.isKinematic = true;
                State = CharacterState.Die;
                _animator.SetBool("Die", true);
                
            }
        }

        public bool CanJump()
        {
            if((State == CharacterState.Idle || State == CharacterState.Move)&&_sensor.IsGrounded) 
            {
                return true;
            }
            return false;
        }

        public bool CanAttack()
        {
            if((State == CharacterState.Idle || State == CharacterState.Move) && _sensor.IsGrounded) 
            {
                return true;
            }
            return false;
        }

        public bool CanMove()
        {
            if(State != CharacterState.Attack && State != CharacterState.Jump) 
            {
                return true;
            }
            return false;
        }
    }
}
